package cn.bugstack.trigger.http;

import cn.bugstack.api.IRAGService;
import cn.bugstack.api.response.Response;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.redisson.client.RedisClient;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.PgVectorStore;
import org.springframework.core.io.PathResource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;

/**
 * @Description: 知识库
 * @ClassName: RAGController
 * @Author: zhaiyongxin
 * @Date: 2025/7/8 14:27
 * @Version: 1.0
 */
@RestController
@RequestMapping("api/v1/rag/")
@Slf4j
@CrossOrigin("*")
public class RAGController implements IRAGService {

    @Resource
    private TokenTextSplitter tokenTextSplitter;
    @Resource
    private PgVectorStore pgVectorStore;
    @Resource
    private RedissonClient redissonClient;
    /**
     * 上传知识库文件
     *
     * @param ragTag
     * @param files
     * @return
     * http://localhost:8090/api/v1/rag/file/upload?ragTag=&file
     */
    @RequestMapping(value = "file/upload", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
    @Override
    public Response<String> uploadFile(@RequestParam("ragTag") String ragTag, @RequestParam("file") List<MultipartFile> files) {
        for (MultipartFile file : files) {
            TikaDocumentReader reader = new TikaDocumentReader(file.getResource());
            List<Document> documents = reader.get();
            List<Document> documentSplitterList  = tokenTextSplitter.apply(documents);
            documents.forEach(doc -> doc.getMetadata().put("knowledge", ragTag));
            documentSplitterList.forEach(doc -> {doc.getMetadata().put("knowledge", ragTag);});
            pgVectorStore.accept(documentSplitterList);

            RList<String> elements = redissonClient.getList("ragTag");
            if (!elements.contains(ragTag)){
                elements.add(ragTag);
            }
        }
        return Response.<String>builder().code("0000").info("调用成功").build();
    }

    /**
     * 获取Rag标识列表
     *
     * @return
     * http://localhost:8090/api/v1/rag/queryRagTagList
     */

    @RequestMapping(value = "queryRagTagList", method = RequestMethod.GET)
    @Override
    public Response<List<String>> queryRagTagList() {
        RList<String> ragTag = redissonClient.getList("ragTag");
        return Response.<List<String>>builder().code("0000")
                .info("调用成功")
                .data(ragTag)
                .build();
    }

    @RequestMapping(value = "analyze_git_repository", method = RequestMethod.POST)
    @Override
    public Response<String> analyzeGitRepository(String repoUrl, String userName, String token) throws IOException, GitAPIException {
        // 1.获取git仓库
        String repoProjectName = extractRepositoryName(repoUrl);
        String localPath = "./git-repository-local";
        log.info("本地git仓库绝对路径为{}", new File(localPath).getAbsolutePath());
        FileUtils.deleteDirectory(new File(localPath));
        // 2.遍历本地git仓库并存储至向量库
        Git git = Git.cloneRepository()
                .setURI(repoUrl)
                .setCredentialsProvider(new UsernamePasswordCredentialsProvider(userName, token))
                .setDirectory(new File(localPath))
                .call();

        Files.walkFileTree(Paths.get(localPath), new SimpleFileVisitor<Path>() {

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                log.info("{} 遍历解析路径，上传知识库:{}", repoProjectName, file.getFileName());
                if (file.toString().contains(".git")){
                    return FileVisitResult.CONTINUE;
                }
                try {
                    PathResource resource = new PathResource(file);
                    TikaDocumentReader reader = new TikaDocumentReader(resource);
                    List<Document> documents = tokenTextSplitter.apply(reader.get());
                    documents.forEach(document -> {
                        document.getMetadata().put("knowledge", repoProjectName);
                    });
                    pgVectorStore.accept(documents);
                } catch (Exception e) {
                    log.error("遍历解析路径，上传知识库失败:{}", file.getFileName());
                }
                return FileVisitResult.CONTINUE;
            }
            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                log.info("Failed to access file: {} - {}", file.toString(), exc.getMessage());
                return FileVisitResult.CONTINUE;
            }
        });



        // 4.存储redis
        RList<String> ragTagList = redissonClient.getList("ragTag");
        if (!ragTagList.contains(repoProjectName)) {
            ragTagList.add(repoProjectName);
        }
        git.close();
        // 3.删除本地仓库
        FileUtils.deleteDirectory(new File(localPath));
        log.info("遍历解析路径，上传完成:{}", repoUrl);
        return Response.<String>builder().code("0000").info("调用成功").build();
    }

    private String extractRepositoryName(String repoUrl) {
        String[] split = repoUrl.split("/");
        String projectName = split[split.length - 1];
        return projectName.replace(".git","");
    }
}
